package com.flycms.common.utils;

import com.flycms.common.utils.text.StrFormatter;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Biz-Boot, All rights reserved
 * 版权：企业之家网 -- 企业建站管理系统<br/>
 * 开发公司：97560.com<br/>
 *
 * 字符串工具类
 * 
 * @author 孙开飞
 */
public class StringUtils extends org.apache.commons.lang3.StringUtils
{
    /** 空字符串 */
    private static final String NULLSTR = "";

    /** 下划线 */
    private static final char SEPARATOR = '_';

    // 手机号正则
    public static final String MOBILEREGEX = "^1[0-9]{10}";
    // email正则
    public static final String EMAILREGEX = "\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}";
    // url正则
    public static final String URLREGEX = "^((https|http)?:\\/\\/)[^\\s]+";
    // 用户名正则
    public static final String USERNAMEREGEX = "[a-z0-9A-Z]{2,16}";
    // 密码正则
    public static final String PASSWORDREGEX = "[a-z0-9A-Z]{6,32}";
    // 生成随机字符串用到的字符数组
    private static final char[] hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
            'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
            'z'};
    // 生成随机长度的数字用到的数组
    private static final char[] digits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    public static final Random random = new Random();

    // 匹配文件名的正则表达式
    private static final String REGEX = "([^<>/\\\\|:\"\"\\*\\?]+)\\.\\w+$+";
    private static final Pattern FILE_NAME_PATTERN = Pattern.compile(REGEX);

    /**
     * 获取参数不为空值
     * 
     * @param value defaultValue 要判断的value
     * @return value 返回值
     */
    public static <T> T nvl(T value, T defaultValue)
    {
        return value != null ? value : defaultValue;
    }

    /**
     * * 判断一个Collection是否为空， 包含List，Set，Queue
     * 
     * @param coll 要判断的Collection
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(Collection<?> coll)
    {
        return isNull(coll) || coll.isEmpty();
    }

    /**
     * * 判断一个Collection是否非空，包含List，Set，Queue
     * 
     * @param coll 要判断的Collection
     * @return true：非空 false：空
     */
    public static boolean isNotEmpty(Collection<?> coll)
    {
        return !isEmpty(coll);
    }

    /**
     * * 判断一个对象数组是否为空
     * 
     * @param objects 要判断的对象数组
     ** @return true：为空 false：非空
     */
    public static boolean isEmpty(Object[] objects)
    {
        return isNull(objects) || (objects.length == 0);
    }

    /**
     * * 判断一个对象数组是否非空
     * 
     * @param objects 要判断的对象数组
     * @return true：非空 false：空
     */
    public static boolean isNotEmpty(Object[] objects)
    {
        return !isEmpty(objects);
    }

    /**
     * * 判断一个Map是否为空
     * 
     * @param map 要判断的Map
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(Map<?, ?> map)
    {
        return isNull(map) || map.isEmpty();
    }

    /**
     * * 判断一个Map是否为空
     * 
     * @param map 要判断的Map
     * @return true：非空 false：空
     */
    public static boolean isNotEmpty(Map<?, ?> map)
    {
        return !isEmpty(map);
    }

    /**
     * * 判断一个字符串是否为空串
     * 
     * @param str String
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(String str)
    {
        return isNull(str) || NULLSTR.equals(str.trim());
    }

    /**
     * * 判断一个字符串是否为非空串
     * 
     * @param str String
     * @return true：非空串 false：空串
     */
    public static boolean isNotEmpty(String str)
    {
        return !isEmpty(str);
    }

    /**
     * * 判断一个对象是否为空
     * 
     * @param object Object
     * @return true：为空 false：非空
     */
    public static boolean isNull(Object object)
    {
        return object == null;
    }

    /**
     * * 判断一个对象是否非空
     * 
     * @param object Object
     * @return true：非空 false：空
     */
    public static boolean isNotNull(Object object)
    {
        return !isNull(object);
    }

    /**
     * * 判断一个对象是否是数组类型（Java基本型别的数组）
     * 
     * @param object 对象
     * @return true：是数组 false：不是数组
     */
    public static boolean isArray(Object object)
    {
        return isNotNull(object) && object.getClass().isArray();
    }

    /**
     * 去空格
     */
    public static String trim(String str)
    {
        return (str == null ? "" : str.trim());
    }

    /**
     * 截取字符串
     * 
     * @param str 字符串
     * @param start 开始
     * @return 结果
     */
    public static String substring(final String str, int start)
    {
        if (str == null)
        {
            return NULLSTR;
        }

        if (start < 0)
        {
            start = str.length() + start;
        }

        if (start < 0)
        {
            start = 0;
        }
        if (start > str.length())
        {
            return NULLSTR;
        }

        return str.substring(start);
    }

    /**
     * 截取字符串
     * 
     * @param str 字符串
     * @param start 开始
     * @param end 结束
     * @return 结果
     */
    public static String substring(final String str, int start, int end)
    {
        if (str == null) {
            return NULLSTR;
        }

        if (end < 0) {
            end = str.length() + end;
        }
        if (start < 0) {
            start = str.length() + start;
        }

        if (end > str.length()) {
            end = str.length();
        }

        if (start > end) {
            return NULLSTR;
        }

        if (start < 0) {
            start = 0;
        }
        if (end < 0) {
            end = 0;
        }

        return str.substring(start, end);
    }

    /**
     * 格式化文本, {} 表示占位符<br>
     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
     * 如果想输出 {} 使用 \\转义 { 即可，如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
     * 例：<br>
     * 通常使用：format("this is {} for {}", "a", "b") -> this is a for b<br>
     * 转义{}： format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
     * 转义\： format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
     * 
     * @param template 文本模板，被替换的部分用 {} 表示
     * @param params 参数值
     * @return 格式化后的文本
     */
    public static String format(String template, Object... params)
    {
        if (isEmpty(params) || isEmpty(template))
        {
            return template;
        }
        return StrFormatter.format(template, params);
    }

    /**
     * 下划线转驼峰命名
     */
    public static String toUnderScoreCase(String str)
    {
        if (str == null)
        {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        // 前置字符是否大写
        boolean preCharIsUpperCase = true;
        // 当前字符是否大写
        boolean curreCharIsUpperCase = true;
        // 下一字符是否大写
        boolean nexteCharIsUpperCase = true;
        for (int i = 0; i < str.length(); i++)
        {
            char c = str.charAt(i);
            if (i > 0)
            {
                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
            }
            else
            {
                preCharIsUpperCase = false;
            }

            curreCharIsUpperCase = Character.isUpperCase(c);

            if (i < (str.length() - 1))
            {
                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
            }

            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
            {
                sb.append(SEPARATOR);
            }
            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
            {
                sb.append(SEPARATOR);
            }
            sb.append(Character.toLowerCase(c));
        }

        return sb.toString();
    }

    /**
     * 去掉字符串指定的前缀
     * @param str 字符串名称
     * @param prefix 前缀数组
     * @return
     */
    public static String removePrefix(String str, String[] prefix) {
        if (StringUtils.isEmpty(str)) {
            return "";
        } else {
            if (null != prefix) {
                String[] prefixArray = prefix;

                for(int i = 0; i < prefix.length; ++i) {
                    String pf = prefixArray[i];
                    if (str.toLowerCase().matches("^" + pf.toLowerCase() + ".*")) {
                        return str.substring(pf.length());//截取前缀后面的字符串
                    }
                }
            }

            return str;
        }
    }

    /**
     * 把骆驼命名法的变量，变为大写字母变小写且之前加下划线
     *
     * @param str
     * @return
     */
    public static String toUnderline(String str) {
        str = org.apache.commons.lang3.StringUtils.uncapitalize(str);
        char[] letters = str.toCharArray();
        StringBuilder sb = new StringBuilder();
        for (char letter : letters) {
            if (Character.isUpperCase(letter)) {
                sb.append("_" + letter + "");
            } else {
                sb.append(letter + "");
            }
        }
        return org.apache.commons.lang3.StringUtils.lowerCase(sb.toString());
    }

    /**
     * 是否包含字符串
     * 
     * @param str 验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    public static boolean inStringIgnoreCase(String str, String... strs)
    {
        if (str != null && strs != null)
        {
            for (String s : strs)
            {
                if (str.equalsIgnoreCase(trim(s)))
                {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。 例如：HELLO_WORLD->HelloWorld
     * 
     * @param name 转换前的下划线大写方式命名的字符串
     * @return 转换后的驼峰式命名的字符串
     */
    public static String convertToCamelCase(String name)
    {
        StringBuilder result = new StringBuilder();
        // 快速检查
        if (name == null || name.isEmpty())
        {
            // 没必要转换
            return "";
        }
        else if (!name.contains("_"))
        {
            // 不含下划线，仅将首字母大写
            return name.substring(0, 1).toUpperCase() + name.substring(1);
        }
        // 用下划线将原始字符串分割
        String[] camels = name.split("_");
        for (String camel : camels)
        {
            // 跳过原始字符串中开头、结尾的下换线或双重下划线
            if (camel.isEmpty())
            {
                continue;
            }
            // 首字母大写
            result.append(camel.substring(0, 1).toUpperCase());
            result.append(camel.substring(1).toLowerCase());
        }
        return result.toString();
    }

    /**
     * 驼峰式命名法 例如：user_name->userName
     */
    public static String toCamelCase(String s)
    {
        if (s == null)
        {
            return null;
        }
        s = s.toLowerCase();
        StringBuilder sb = new StringBuilder(s.length());
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++)
        {
            char c = s.charAt(i);

            if (c == SEPARATOR)
            {
                upperCase = true;
            }
            else if (upperCase)
            {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            }
            else
            {
                sb.append(c);
            }
        }
        return sb.toString();
    }


    public static boolean check(String text, String regex) {
        if (org.springframework.util.StringUtils.isEmpty(text)) {
            return false;
        } else {
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(text);
            return matcher.matches();
        }
    }

    /**
     * 随机指定长度的字符串
     *
     * @param length
     * @return
     */
    public static String randomString(int length) {
        StringBuilder sb = new StringBuilder();
        for (int loop = 0; loop < length; ++loop) {
            sb.append(hexDigits[random.nextInt(hexDigits.length)]);
        }
        return sb.toString();
    }

    /**
     * 随机指定长度的数字
     *
     * @param length
     * @return
     */
    public static String randomNumber(int length) {
        StringBuilder sb = new StringBuilder();
        for (int loop = 0; loop < length; ++loop) {
            sb.append(digits[random.nextInt(digits.length)]);
        }
        return sb.toString();
    }

    // 生成一个uuid
    public static String uuid() {
        return UUID.randomUUID().toString();
    }

    /**
     * 检测是否是用户accessToken
     */
    public static boolean isUUID(String accessToken) {
        if (org.springframework.util.StringUtils.isEmpty(accessToken)) {
            return false;
        } else {
            try {
                // noinspection ResultOfMethodCallIgnored
                UUID.fromString(accessToken);
                return true;
            } catch (Exception e) {
                return false;
            }
        }
    }

    // 格式化url参数部分返回map
    // params格式：a=1&b=2&c=3
    // 返回：{a: 1, b: 2, c: 3}
    public static Map<String, Object> formatParams(String params) {
        if (org.springframework.util.StringUtils.isEmpty(params)) return null;
        Map<String, Object> map = new HashMap<>();
        for (String s : params.split("&")) {
            String[] ss = s.split("=");
            map.put(ss[0], ss[1]);
        }
        return map;
    }

    // 查找评论里at的用户名
    public static List<String> fetchAtUser(String content) {
        if (org.springframework.util.StringUtils.isEmpty(content)) return Collections.emptyList();
        // 去掉 ``` ``` 包围的内容
        content = content.replaceAll("```([\\s\\S]*)```", "");
        // 去掉 ` ` 包围的内容
        content = content.replaceAll("`([\\s\\S]*)`", "");
        // 找到@的用户
        String atRegex = "@[a-z0-9-_]+\\b?";
        List<String> atUsers = new ArrayList<>();
        Pattern regex = Pattern.compile(atRegex);
        Matcher regexMatcher = regex.matcher(content);
        while (regexMatcher.find()) {
            atUsers.add(regexMatcher.group());
        }
        return atUsers;
    }

    // 去掉数组里的空值和重复数据
    public static Set<String> removeEmpty(String[] strs) {
        if (strs == null || strs.length == 0) return Collections.emptySet();
        Set<String> set = new HashSet<>();
        for (String str : strs) {
            if (!org.springframework.util.StringUtils.isEmpty(str)) {
                set.add(str);
            }
        }
        return set;
    }

    /**
     * 获取二级域名前缀
     *
     * @param url
     * @return
     */
    public static String twoStageDomain(String url) {
        //String url = "http://blog.abc.com/entry/4545/0/";
        Pattern p = Pattern.compile("(http://||https://)(\\w+)\\.(\\w+)\\.(com.cn|net.cn|gov.cn|org\\.nz|org.cn|com|net|org|gov|cc|biz|info|cn|co)",Pattern.CASE_INSENSITIVE);
        Matcher matcher = p.matcher(url);
        String textStr = "";
        while (matcher.find()) {
            textStr = matcher.group(2);
        }
        return textStr;
    }

    /**
     * 获取图片地址的图片后缀
     *
     * @param url
     *        网络图片地址
     * @return
     */
    public static String getImageUrlSuffix(String url){
        Pattern p =Pattern.compile("\\/[^\\/]*\\.(jpg|jpeg|gif|png|bmp)\\??[^?]*$", Pattern.CASE_INSENSITIVE);
        Matcher matcher = p.matcher(url);
        String regex ="";
        if(matcher.find()){
            regex = matcher.group(1);
        }
        return regex;
    }

    /**
     * 获取url中的域名
     *
     * @param url
     * @return
     */
    public static String stringDomain(String url) {
        //String url = "http://www.linuxidc.com/entry/4545/0/";
        Pattern p = Pattern.compile("(http://||https://)(\\w+)\\.(\\w+)\\.(com.cn|net.cn|gov.cn|org\\.nz|org.cn|com|net|org|gov|cc|biz|info|cn|co|cc|tv)",Pattern.CASE_INSENSITIVE);
        Matcher matcher = p.matcher(url);
        String textStr = "";
        while (matcher.find()) {
            textStr = matcher.group(2);
        }
        matcher.find();
        System.out.println(matcher.group());
        return textStr;
    }

    //正则获取url里的图片文件名称
    public static String getFileName(String path) {
        Matcher matcher = FILE_NAME_PATTERN.matcher(path);
        // 使用while循环是因为一般匹配时存在多个匹配项，此例中只会匹配一个，也可直接用if判断
        while (matcher.find()) {
            String group = matcher.group(1);
            return group;
        }
        // 未匹配到
        return null;
    }

    /**
     * @param str       原字符串
     * @param indexStr  指定字符串
     * @param isInclude 是否包括指定字符串
     * @return 截取后的字符串
     */
    public static String getLastindexStr(String str, String indexStr, boolean isInclude) {
        String result = "";
        int start = str.lastIndexOf(indexStr);
        if (start == -1) {
            return result = "";
        } else {
            if (isInclude) {
                result = str.substring(start);
            } else {
                result = str.substring(start + indexStr.length() + 1);
            }
            return result.substring(0, result.length() - 1);
        }
    }

    /**
     * @param str       原字符串
     * @param replaceStr  指定字符串
     * @return 截取后的字符串
     */
    public static String getReplaceStr(String str, String replaceStr) {
        String newsStr = str.replace(replaceStr, "");
        return newsStr;
    }

    public static void main(String[] args) {
        /*System.out.println(getFileName("D:/test/test.txt"));
        System.out.println(getFileName("D:/test/test.doc"));
        System.out.println(getFileName("D:/test/abc/test2.xls"));*/
        String url = "http://www.linuxidc.com/entry/4545/0/";
        String urlsss = "www.abc.com";
        System.out.println(twoStageDomain(urlsss));
    }
}